﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace AutoUI
{
    /// <summary>
    /// 封装生成高级衍生图形的各种静态方法
    /// </summary>
    public static class Shapes
    {
        #region Methods

        /// <summary>
        /// 创建指针
        /// </summary>
        /// <param name="stytle"></param>
        /// <param name="w">长度</param>
        /// <param name="h">高度</param>
        /// <returns></returns>
        public static GraphicsPath CreateNeedle(EnumStytle stytle, float w, float h)
        {
            GraphicsPath gp = new GraphicsPath();
            switch (stytle)
            {
                case EnumStytle.Stytle1:
                    gp.AddRectangle(new RectangleF(0, -h / 2, w, h));
                    break;

                case EnumStytle.Stytle2:
                    CircleF c = new CircleF(new PointF(0, 0), h);

                    gp.AddArc(c, 90, 180);
                    gp.AddLine(new PointF(w, 0), new PointF(0, h));
                    gp.CloseFigure();
                    break;

                case EnumStytle.Stytle3:
                    break;

                case EnumStytle.Stytle4:
                    break;

                default:
                    break;
            }
            return gp;
        }

        /// <summary>
        /// 创建一个带圆角的矩形
        /// </summary>
        /// <param name="rect">矩形边框</param>
        /// <param name="radius">圆角半径</param>
        /// <returns>一个GraphicsPath对象,表示创建的钝角矩形</returns>
        public static GraphicsPath CreateRoundedRectangle(RectangleF rect, float radius)
        {
            GraphicsPath gp = new GraphicsPath();
            if (radius <= 0) { gp.AddRectangle(rect); return gp; }
            gp.AddArc(rect.Right - 2 * radius, rect.Top, radius * 2, radius * 2, 270, 90);
            gp.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);
            gp.AddArc(rect.Left, rect.Bottom - 2 * radius, 2 * radius, 2 * radius, 90, 90);
            gp.AddArc(rect.Left, rect.Top, 2 * radius, 2 * radius, 180, 90);
            gp.CloseFigure();
            return gp;
        }

        internal static GraphicsPath CreateNeedle(PointF pointF, float w, float h, EnumStytle style)
        {
            GraphicsPath gp = new GraphicsPath();
            switch (style)
            {
                case EnumStytle.Stytle1:
                    gp.AddRectangle(new RectangleF((-w / 2) + pointF.X, -h / 2, w, h));
                    break;

                case EnumStytle.Stytle2:
                    CircleF c = new CircleF(pointF, h);

                    gp.AddArc(c, 90, 180);
                    gp.AddLine(new PointF(w + pointF.X, 0), new PointF(pointF.X, h));
                    gp.CloseFigure();
                    break;

                case EnumStytle.Stytle3:
                    break;

                case EnumStytle.Stytle4:
                    break;

                default:
                    break;
            }
            return gp;
        }

        /// <summary>
        ///创建多边形
        /// </summary>
        /// <param name="center">多边形圆心</param>
        /// <param name="radius">多边形外接圆半径</param>
        /// <param name="count">多边形边数</param>
        /// <returns></returns>
        public static GraphicsPath CreateRegularPolygon(PointF center, float radius, int count)
        {
            GraphicsPath gp = new GraphicsPath();
            CircleF c = new CircleF(center, radius);
            PointF[] ret = new PointF[count + 1];
            float ang = 360.0f / count;
            for (int i = 0; i <= count; i++)
            {
                ret[i] = c.PointOnPath(i * ang);
            }
            gp.AddLines(ret);
            return gp;
        }

        /// <summary>
        /// 创建正多边形的顶点数组。
        ///  </summary>
        /// <param name="pivot">正多边形的几何中心坐标。</param>
        /// <param name="outterRadius">多边形的外接圆半径。</param>
        /// <param name="points">多边形的边数。</param>
        /// <param name="angleOffset">X轴顶角坐标偏移度数。</param>
        /// <returns>正多边形的顶点数组。</returns>
        public static PointF[] CreateRegularPolygon(PointF pivot, float outterRadius, int points, float angleOffset = 0.0f)
        {
            if (outterRadius < 0) throw new ArgumentOutOfRangeException("outterRadius", "多边形的外接圆半径必须大于0");
            if (points < 3) throw new ArgumentOutOfRangeException("points", "多边形的边数必须大于等于3");
            PointF[] ret = new PointF[points];
            CircleF c = new CircleF(pivot, outterRadius);
            float ang = 360.0f / points;
            for (int i = 0; i < points; i++)
            {
                ret[i] = c.PointOnPath(angleOffset + i * ang);
            }
            return ret;
        }

        /// <summary>
        /// 创建心形(正五角星的内圆半径比例为:0.381966011250105,角度为36)
        /// </summary>
        /// <param name="offsetpoint"></param>
        /// <param name="length"></param>
        /// <param name="h"></param>
        /// <param name="count"></param>
        /// <param name="style"></param>
        /// <returns></returns>
        internal static GraphicsPath CreateStar(PointF offsetpoint, float length, float h, int count, EnumStytle style)
        {
            GraphicsPath gp = new GraphicsPath();
            switch (style)
            {
                case EnumStytle.Stytle1:
                    gp = CreateStar(offsetpoint, length, length * h, count);
                    break;

                case EnumStytle.Stytle2:
                    gp = CreateRandomStar(offsetpoint, length, length * h, count);
                    break;

                case EnumStytle.Stytle3:
                    gp = CreateStar(offsetpoint, length, length * h, count);

                    break;

                case EnumStytle.Stytle4:
                    break;

                default:
                    break;
            }
            return gp;
        }

        /// <summary>
        /// 创建一个几何规则的星形(正五角星的内圆半径比例为:0.381966011250105,角度为36)
        /// </summary>
        /// <param name="pivot">星形的几何中心坐标</param>
        /// <param name="outterRadius">星形的外环半径</param>
        /// <param name="innerRadius">星形的内环半径</param>
        /// <param name="points">星形的顶角数</param>
        /// <param name="angleOffset">X轴顶角坐标偏移度数。</param>
        /// <returns>星形的GraphicsPath对象</returns>
        public static GraphicsPath CreateStar(PointF pivot, float outterRadius, float innerRadius, int points, float angleOffset = 0f)
        {
            if (outterRadius <= innerRadius) throw new ArgumentException("参数outterRadius必须大于innerRadius。");
            if (points < 2) throw new ArgumentOutOfRangeException("points");
            GraphicsPath gp = new GraphicsPath();
            CircleF outter = new CircleF(pivot, outterRadius);
            CircleF inner = new CircleF(pivot, innerRadius);
            float ang = 360.0f / points;
            for (int i = 0; i < points; i++)
            {
                gp.AddLine(outter.PointOnPath(angleOffset + i * ang), inner.PointOnPath(angleOffset + i * ang + ang / 2.0f));
            }
            gp.CloseFigure();
            return gp;
        }

        /// <summary>
        /// 创建静态的环形刻度线,带起始角度和划过角度
        /// </summary>
        /// <param name="centerpoint">圆心</param>
        /// <param name="TickRadius">刻度半径</param>
        /// <param name="Length">刻度长度占刻度半径的比例(0-1)</param>
        /// <param name="Count">刻度个数</param>
        /// <param name="StartAngle">开始角度</param>
        /// <param name="SweepAngle">结束角度</param>
        /// <param name="style">等待丰富中.........</param>
        /// <returns></returns>
        internal static GraphicsPath CreateWaitCircleSpoke(PointF centerpoint, float TickRadius, float Length, int Count, float StartAngle, float SweepAngle, EnumStytle style)
        {
            GraphicsPath path = new GraphicsPath();
            CircleF circle_in = new CircleF(centerpoint, TickRadius);
            CircleF circle_out = new CircleF(centerpoint, TickRadius * (1 - Length));
            var interval = SweepAngle / Count;
            for (int i = 0; i <= Count; i++)
            {
                var p1 = circle_in.PointOnPath(StartAngle + interval * i);
                var p2 = circle_out.PointOnPath(StartAngle + interval * i);
                path.AddLine(p1, p2);
                path.StartFigure();
            }
            return path;
        }

        /// <summary>
        /// 创建不规则的N角星
        /// </summary>
        /// <param name="pivot">圆心</param>
        /// <param name="outterRadius">最大星角的半径</param>
        /// <param name="innerRadius">内圆半径</param>
        /// <param name="points">星角个数</param>
        /// <param name="angleOffset"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static GraphicsPath CreateRandomStar(PointF pivot, float outterRadius, float innerRadius, int points, float angleOffset = 0f)
        {
            Random random = new Random();
            if (outterRadius <= innerRadius) throw new ArgumentException("参数outterRadius必须大于innerRadius。");
            if (points < 2) throw new ArgumentOutOfRangeException("points");
            GraphicsPath gp = new GraphicsPath();
            float ang = 360.0f / points;
            var ranbase = outterRadius - innerRadius;
            CircleF inner = new CircleF(pivot, innerRadius);
            for (int i = 0; i < points; i++)
            {
                var p1 = (float)random.NextDouble() * ranbase + innerRadius;
                CircleF outter = new CircleF(pivot, p1);
                gp.AddLine(outter.PointOnPath(angleOffset + i * ang), inner.PointOnPath(angleOffset + i * ang + ang / 2.0f));
            }
            gp.CloseFigure();
            return gp;
        }

        /// <summary>
        /// 创建进度圆环的各个叶瓣的轮廓线
        /// </summary>
        /// <param name="pivot">进度圆环的几何中心坐标</param>
        /// <param name="outterRadius">进度圆环的外边界半径</param>
        /// <param name="innerRadius">进度圆环的内边界半径</param>
        /// <param name="spokes">进度圆环的叶瓣数量</param>
        /// <param name="angleOffset">X轴顶角坐标偏移度数</param>
        /// <returns>组成进度圆环的各个叶瓣的轮廓线坐标链表</returns>
        public static List<PointF[]> CreateWaitCircleSpokes(PointF pivot, float outterRadius, float innerRadius, int spokes, float angleOffset = 0.0f)
        {
            if (spokes < 1) throw new ArgumentException("参数spokes必须大于等于1。");
            List<PointF[]> lst = new List<PointF[]>();
            CircleF outter = new CircleF(pivot, outterRadius);
            CircleF inner = new CircleF(pivot, innerRadius);
            float ang = 360.0f / spokes;
            for (int i = 0; i < spokes; i++)
            {
                lst.Add(new PointF[2] { outter.PointOnPath(angleOffset + i * ang), inner.PointOnPath(angleOffset + i * ang) });
            }
            return lst;
        }

        #endregion Methods
    }
}